#include <stdio.h>
#include <string.h>
#include "kfifo.h"
#include "main.h"	
#include "earbud_cmd.h"
#include "earbud_wq_comm.h"
#include "msg.h"
#include "hall.h"
#include "sw_timer.h"
#include "usart.h"
#include "sy8801.h"
#include "app_user.h"
#include "tim.h"


//-HIGH_100MS-|S |---------OPCODE--------|P |S |--------PARAM----------|P |
//____________    __    __    __    __    __    __    __    __    __    __
//            |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|


#if (SUPPORT_WQ_COMM)

uint8_t wq_comm_en = 0;

uint8_t wq_comm_state = STAGE_IDLE;
uint8_t wq_comm_role = 0;
uint8_t wq_comm_opcode = 0;
uint8_t wq_comm_opcode_new = 0;
uint8_t wq_comm_param = 0;
uint8_t wq_comm_data = 0;
uint8_t wq_comm_index = 0;
uint8_t wq_comm_timer = 0xff;
uint8_t wq_comm_count = 0;



void earbud_wq_comm_tim_callback(void)
{
    switch(wq_comm_state)
    {
        case STAGE_IDLE:
            break;
        case STAGE_HIGH_100MS:
            //BOX_LOG("wq comm start\n");
            sy8801_ear_5v_output_enable(wq_comm_role);     //HIGH_100MS
            HAL_TIM7_stop();
            HAL_TIM7_start(10000);      //100ms
            wq_comm_state = STAGE_OPCODE_START;
            break;
        case STAGE_OPCODE_START:
            sy8801_ear_5v_output_disable(wq_comm_role);    //S
            HAL_TIM7_stop();
            HAL_TIM7_start(1000);      //10ms
            wq_comm_state = STAGE_OPCODE;
            break;
        case STAGE_OPCODE:
            if(wq_comm_index == 0)
                wq_comm_data = wq_comm_opcode;

            if(wq_comm_data & 0x01)
                sy8801_ear_5v_output_enable(wq_comm_role);
            else
                sy8801_ear_5v_output_disable(wq_comm_role);
            wq_comm_data >>= 1;
            wq_comm_index++;
            if(wq_comm_index > 7)
            {
                wq_comm_index = 0;
                wq_comm_state = STAGE_OPCODE_STOP;
            }
            break;
        case STAGE_OPCODE_STOP:
            sy8801_ear_5v_output_enable(wq_comm_role);     //P
            wq_comm_state = STAGE_PARAM_START;
            break;
        case STAGE_PARAM_START:
            sy8801_ear_5v_output_disable(wq_comm_role);    //S
            wq_comm_state = STAGE_PARAM;
            break;
        case STAGE_PARAM:
            if(wq_comm_index == 0)
                wq_comm_data = wq_comm_param;

            if(wq_comm_data & 0x01)
                sy8801_ear_5v_output_enable(wq_comm_role);
            else
                sy8801_ear_5v_output_disable(wq_comm_role);
            wq_comm_data >>= 1;
            wq_comm_index++;
            if(wq_comm_index > 7)
            {
                wq_comm_index = 0;
                wq_comm_state = STAGE_PARAM_STOP;
            }
            break;
        case STAGE_PARAM_STOP:
            sy8801_ear_5v_output_enable(wq_comm_role);     //P
            wq_comm_state = STAGE_END;
            break;
        case STAGE_END:
            sy8801_ear_5v_output_disable(wq_comm_role);
            HAL_TIM7_stop();
            wq_comm_state = STAGE_IDLE;
            if(wq_comm_opcode_new != 0)
                wq_comm_opcode = wq_comm_opcode_new;
            //BOX_LOG("wq comm end\n");
            wq_comm_count++;
            if(wq_comm_opcode == BOX_MSG_OPT_CODE_BOX_CLOSE && wq_comm_count > 3)
            {
                BOX_LOG("box close\n");
                app_close_box_callback(EAR_L);
                app_close_box_callback(EAR_R);
            }
            break;
    }
}

void earbud_wq_comm_send_data(void)
{
#if 0
    uint8_t OPCODE = 0x50;
    uint8_t PARAM = 0x0A;
    uint8_t i;
    
    BOX_LOG("wq comm test\n");
    sy8801_ear_5v_output_enable(wq_comm_role);     //HIGH_100MS
    HAL_Delay(100);
    sy8801_ear_5v_output_disable(wq_comm_role);    //S
    HAL_Delay(10);

    for(i=0; i<8; i++)
    {
        if(OPCODE & 0x01)
            sy8801_ear_5v_output_enable(wq_comm_role);
        else
            sy8801_ear_5v_output_disable(wq_comm_role);
        OPCODE >>= 1;
        HAL_Delay(9);
    }

    sy8801_ear_5v_output_enable(wq_comm_role);     //P
    HAL_Delay(9);
    sy8801_ear_5v_output_disable(wq_comm_role);    //S
    HAL_Delay(9);

    for(i=0; i<8; i++)
    {
        if(PARAM & 0x01)
            sy8801_ear_5v_output_enable(wq_comm_role);
        else
            sy8801_ear_5v_output_disable(wq_comm_role);
        PARAM >>= 1;
        HAL_Delay(9);
    }

    sy8801_ear_5v_output_enable(wq_comm_role);     //P
    HAL_Delay(9);
    sy8801_ear_5v_output_disable(wq_comm_role);
#else
    BOX_LOG("wq_comm_state: %d\n", wq_comm_state);
    if(wq_comm_state == STAGE_IDLE)
    {
        wq_comm_state = STAGE_HIGH_100MS;
        earbud_wq_comm_tim_callback();
    }
#endif
}

void earbud_wq_comm_start(void)
{
    sy8801_auto_detect_disable();

    wq_comm_role = 0x03;
    wq_comm_opcode = 0x50;
    wq_comm_param = 0x0a;

    earbud_wq_comm_stop();
    wq_comm_timer = sw_timer_start(3000, 1, earbud_wq_comm_send_data);

    BOX_LOG("wq comm start: %d\n", wq_comm_timer);
}

void earbud_wq_comm_stop(void)
{
    if(wq_comm_timer != 0xff)
        wq_comm_timer = sw_timer_stop(wq_comm_timer);
}

void earbud_delay_start_comm(uint8_t role)
{
    BOX_LOG("wq delay start comm\n");
    wq_comm_en = 1;
    app_sy880x_heartbeat_timer_stop();
    earbud_wq_comm_start();
}

void earbud_stop_comm(uint8_t role)
{
    BOX_LOG("wq stop comm\n");
    wq_comm_en = 0;
    earbud_wq_comm_stop();

    app_sy880x_heartbeat_timer_start();
    sy8801_auto_detect_enable();
}

uint8_t earbud_wq_comm_is_en(void)
{
    return wq_comm_en;
}

void earbud_comm_delay_timer_stop(uint8_t role)
{
}

uint8_t earbud_comm_is_activity(uint8_t role)
{
    return 0;
}

void earbud_enter_pair(void)
{
    earbud_comm_send_cmd(0, CMD_PAIRING);
}

void earbud_factory_reset(void)
{
    earbud_comm_send_cmd(0, CMD_FACTORY_RESET_KEEP_WWS);
}

void earbud_cmd_clear(uint8_t role)
{

}


void earbud_comm_send_cmd(uint8_t role, uint8_t cmd)
{
    uint8_t cur_cmd;

    switch(cmd)
    {
        case CMD_OPENCASE:
            cur_cmd = BOX_MSG_OPT_CODE_BOX_OPEN;
            break;
        case CMD_CLOSECASE:
            cur_cmd = BOX_MSG_OPT_CODE_BOX_CLOSE;
            if(wq_comm_timer != 0xff)
                sw_timer_update(wq_comm_timer, 800);
            break;
        case CMD_PAIRING:
            cur_cmd = BOX_MSG_OPT_CODE_ENTER_PAIR; 
            break;
        case CMD_FACTORY_RESET_KEEP_WWS:
            cur_cmd = BOX_MSG_OPT_CODE_RECONFIG;
            break;
        case CMD_DUT_MODE:
            cur_cmd = BOX_MSG_OPT_CODE_ENTER_DUT;
            break;
        default:
            BOX_LOG("unknown cmd\n");
            break;
    }
    //BOX_LOG("cmd push: %d, 0x%x\n", role, cmd);
   
    if(wq_comm_state == STAGE_IDLE)
        wq_comm_opcode = cur_cmd;
    else
        wq_comm_opcode_new = cur_cmd;

    wq_comm_count = 0;
}

void earbud_wq_comm_init(void)
{
    
}

void earbud_wq_comm_deinit(void)
{
    
}

#endif

